package SocketTest.IO;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;


/**
 * 双向通信socket服务端简单示例
 * @author chenjunjie
 * @since 2018-04-17
 */
public class Server {
    //搭建服务器端
    public static void main(String[] args) throws IOException {
        Server socketService = new Server();
        //创建一个服务器端Socket，即SocketService 
        socketService.oneServer();
        //
        //socketService.manyServer();
    }

    protected void oneServer() {
        ServerSocket server = null;
        //1. 生成socket服务对象，制定监听端口
        try {
            server = new ServerSocket(5200);
            System.out.println("启动服务...");

        } catch (IOException e) {
           e.printStackTrace();
        }

        Socket clientSocket = null;
        //2. 监听，收到socket后开始响应
        try {
            //阻塞，直到监听到客户端请求
            clientSocket = server.accept();
            System.out.println("监听");
        } catch (IOException e) {
            e.printStackTrace();
        }

        //3. 读取用户端输入流
        InputStream inputStream = null;
        try {
            inputStream = clientSocket.getInputStream();
            int k;
            StringBuilder sb = new StringBuilder();
            byte[] bytes = new byte[1024];
            //当客户端关闭它的输出流的时候，服务端才能取得结尾的-1，注意一下客户端中是否有socket.shutdownOutput()
            while ((k = inputStream.read(bytes)) != -1){
                sb.append(new String(bytes, 0, k, "UTF-8"));
            }
            System.out.println("get message from client: " + sb);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //4.响应客户端请求
        OutputStream outputStream = null;
        try {
            outputStream = clientSocket.getOutputStream();
            outputStream.write("你好客户端, I will processe you request later".getBytes("UTF-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //5.关闭输入输出流
        try {
            inputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //6.关闭socket
        try {
            clientSocket.close();
            server.close();
            System.out.println("关闭服务");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 处理多个客户端socket请求，实际场景下的模型
     * 加入循环处理
     */
    protected void manyServer() throws IOException {
        ServerSocket server = null;
        //1. 生成socket服务对象，制定监听端口
        try {
            server = new ServerSocket(5200);
            System.out.println("启动服务...");

        } catch (IOException e) {
            e.printStackTrace();
        }
        //如果使用多线程，那就需要线程池，防止并发过高时创建过多线程耗尽资源
        Executor threadPool = Executors.newFixedThreadPool(20);

        while (true) {
            //每次监听到一个用户的请求就生成一个线程，负责处理这个socket对象
            Socket socket = server.accept();
            Thread thread = new ServerSocketThread(socket);
            threadPool.execute(thread);
        }
    }
}

class ServerSocketThread extends Thread {
    private Socket socket;
    public ServerSocketThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        // 建立好连接后，从socket中获取输入流，并建立缓冲区进行读取
        InputStream inputStream = null;
        try {
            byte[] bytes = new byte[1024];
            int len;
            StringBuilder sb = new StringBuilder();
            inputStream = socket.getInputStream();
            while ((len = inputStream.read(bytes)) != -1) {
                sb.append(new String(bytes, 0, len, "UTF-8"));
            }
            System.out.println("get message from client: " + sb);
            inputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
